package ZooManagement;

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

/**
 * ZooService - Core API for managing zoo operations
 */
public class ZooService {
    private final Zoo southernZone;
    private final Zoo northernZone;
    private final Scanner input;
    private boolean running;

    public ZooService() {
        this.southernZone = new Zoo("Southern-Zone Zoo");
        this.northernZone = new Zoo("Northern-Zone Zoo");
        this.input = new Scanner(System.in);
        this.running = false;
        initializeZoos();
    }

    /**
     * Initialize both zoos with default animals
     */
    private void initializeZoos() {
        // Southern-Zone animals
        addAnimal(southernZone, "Simba", "African Lion", 6);
        addAnimal(southernZone, "Dumbo", "African Elephant", 12);
        addAnimal(southernZone, "Luna", "Gray Wolf", 4);
        addAnimal(southernZone, "Poe", "Raven", 3);
        addAnimal(southernZone, "Benny", "Grizzly Bear", 8);

        // Northern-Zone animals
        addAnimal(northernZone, "Arctic", "Polar Bear", 7);
        addAnimal(northernZone, "Blizzard", "Snow Leopard", 5);
        addAnimal(northernZone, "Frost", "Arctic Fox", 3);
        addAnimal(northernZone, "Penguin", "Emperor Penguin", 4);
        addAnimal(northernZone, "Aurora", "Caribou", 6);
    }

    /**
     * Starts the zoo management service
     */
    public void start() {
        this.running = true;
        System.out.println("Zoo Management Service started");
    }

    /**
     * Stops the zoo management service
     */
    public void stop() {
        this.running = false;
        input.close();
        System.out.println("Zoo Management Service stopped");
    }

    /**
     * Displays all animals in the specified zoo
     * @param zooName "Southern-Zone" or "Northern-Zone"
     * @return List of formatted animal information strings
     */
    public List<String> displayAnimals(String zooName) {
        Zoo zoo = getZooByName(zooName);
        if (zoo == null) {
            return List.of("Invalid zoo name");
        }

        List<String> animalInfo = new ArrayList<>();
        animalInfo.add("----- Animals in " + zoo.getName() + " (" + zoo.getCounter() + "/10) -----");

        if (zoo.getCounter() == 0) {
            animalInfo.add("There are no animals in this zoo.");
        } else {
            for (int i = 0; i < zoo.getCounter(); i++) {
                Animal animal = zoo.getAnimal(i);
                animalInfo.add((i + 1) + ". Name: " + animal.getName() +
                        ", Species: " + animal.getSpecies() +
                        ", Age: " + animal.getAge());
            }
        }
        animalInfo.add("---------------------------------------------");
        return animalInfo;
    }

    /**
     * Moves an animal between zoos with logistics details
     * @param animalName Name of animal to move
     * @param fromZoo Source zoo name
     * @param toZoo Destination zoo name
     * @param vehicle Transport vehicle item
     * @param fuel Fuel item
     * @param caretakers List of caretaker names
     * @return true if move was successful
     */
    public boolean moveAnimal(String animalName, String fromZoo, String toZoo,
                              Item vehicle, Item fuel, List<String> caretakers) {
        Zoo source = getZooByName(fromZoo);
        Zoo destination = getZooByName(toZoo);

        if (source == null || destination == null) {
            return false;
        }

        int animalIndex = source.findAnimal(animalName);
        if (animalIndex == -1) {
            return false;
        }

        if (destination.getCounter() >= 10) {
            System.out.println("Destination zoo is full!");
            return false;
        }

        Logistics logistics = new Logistics(vehicle, fuel, caretakers.toArray(new String[0]));
        Animal animal = source.getAnimal(animalIndex);

        destination.addAnimal(animal);
        source.deleteAnimal(animalName);

        logistics.display(source.getName(), destination.getName(), animal);
        return true;
    }

    /**
     * Adds a new animal to the specified zoo
     * @param zooName "Southern-Zone" or "Northern-Zone"
     * @param name Animal name
     * @param species Animal species
     * @param age Animal age
     * @return true if addition was successful
     */
    public boolean addAnimal(String zooName, String name, String species, int age) {
        Zoo zoo = getZooByName(zooName);
        if (zoo == null || zoo.getCounter() >= 10) {
            return false;
        }

        if (name == null || name.trim().isEmpty() ||
                species == null || species.trim().isEmpty() ||
                age < 0) {
            return false;
        }

        zoo.addAnimal(new Animal(name, species, age));
        return true;
    }

    /**
     * Removes an animal from the specified zoo
     * @param zooName "Southern-Zone" or "Northern-Zone"
     * @param animalName Name of animal to remove
     * @return true if removal was successful
     */
    public boolean removeAnimal(String zooName, String animalName) {
        Zoo zoo = getZooByName(zooName);
        if (zoo == null || animalName == null || animalName.trim().isEmpty()) {
            return false;
        }

        return zoo.findAnimal(animalName) != -1 && zoo.deleteAnimal(animalName);
    }

    /**
     * Finds an animal in either zoo
     * @param animalName Name of animal to find
     * @return Animal object if found, null otherwise
     */
    public Animal findAnimal(String animalName) {
        if (animalName == null || animalName.trim().isEmpty()) {
            return null;
        }

        Animal animal = southernZone.getAnimalByName(animalName);
        return animal != null ? animal : northernZone.getAnimalByName(animalName);
    }

    /**
     * Gets the current animal count in a zoo
     * @param zooName "Southern-Zone" or "Northern-Zone"
     * @return Number of animals, or -1 for invalid zoo name
     */
    public int getAnimalCount(String zooName) {
        Zoo zoo = getZooByName(zooName);
        return zoo != null ? zoo.getCounter() : -1;
    }

    /**
     * Checks if service is running
     * @return true if service is active
     */
    public boolean isRunning() {
        return running;
    }

    /**
     * Gets the zoo object by name
     * @param zooName "Southern-Zone" or "Northern-Zone"
     * @return Zoo object or null if not found
     */
    public Zoo getZoo(String zooName) {
        return getZooByName(zooName);
    }

    private Zoo getZooByName(String zooName) {
        if (zooName == null) {
            return null;
        }

        if (zooName.equalsIgnoreCase("Southern-Zone")) {
            return southernZone;
        } else if (zooName.equalsIgnoreCase("Northern-Zone")) {
            return northernZone;
        }
        return null;
    }

    private void addAnimal(Zoo zoo, String name, String species, int age) {
        zoo.addAnimal(new Animal(name, species, age));
    }
}